#include "comm.hpp"
Init init;
string TransToHex(key_t k)//转化为十六进制,用于把key从10进制转化成16进制形式
{
    char buffer[32];
    snprintf(buffer,sizeof buffer,"0x%x",k);//向buffer字符串里面写
    return buffer;
}


int main()
{
    //1.创建公共的key
    key_t k=ftok(PATH_NAME,PROJ_ID);//ftok用于创建唯一的key
    assert(k!=-1);//如果创建失败会返回-1
    Log("create key done ",Debug)<<"server key: "<<TransToHex(k)<<endl;



    //2.创建共享内存--建议创建一个全新的共享内存--通信发起者
    int shmid=shmget(k,SHM_SIZE,IPC_CREAT|IPC_EXCL|0666);
    if(shmid==-1)//如果创建失败则返回-1
    {
        perror("shmget ");
        exit(1);
    }
    Log("create shm done ",Debug)<<"shmid: "<<shmid<<endl;



    // sleep(10);
    //3.将指定共享内存与自己进程的地址空间 链接 到一起
    char *shmaddr=(char*)shmat(shmid,nullptr,0);//nullptr，默认链接一个合适的虚拟地址空间；0，默认读写功能；返回值：地址空间上，共享内存段的地址
    Log("attach shm done ",Debug)<<"shmid: "<<shmid<<endl;

    //sleep(10);







    //4.通信（读）
    //shmaddr就是物理内存在虚拟地址空间中的链接的地址，向shmaddr写入，也就是向shmid的共享内存中写入
    //shmaddr可以看成是一个大字符串
    //方法1.写端：直接向shmaddr中写入即可，因为是内存级别操作，不需要像管道一样先到buffer，再从buffer刷到管道文件。这里没有涉及文件，是存内存层面的操作
    //      读端：直接从shamddr中读即可。
    
    //方法2：在方法1基础上加上访问控制
     int fd=OpenFIFO(FIFO_NAME,READ);//写端以写的方式创建(没有就创建，有就打开)管道文件
    for(;;)
    {
        Wait(fd);//读端等待写入
        printf("%s\n",shmaddr);
        if(strcmp(shmaddr,"quit")==0)
        {
            printf("client already quit, server quit too\n");
            break;
        }
        // sleep(1);
    }
    



    //5.将指定的共享内存，从自己的地址空间中去关联（去链接）
    int n=shmdt(shmaddr);
    assert(n!=-1);
    (void)n;
    Log("detach shm done ",Debug)<<"shmid: "<<shmid<<endl;
    // sleep(10);



    //6.删除共享内存，IPC_RMID即便是有进程和当下shm挂接，依旧删除共享内存
    n=shmctl(shmid,IPC_RMID,nullptr);
    assert(n!=-1);
    (void)n;
    Log("delete shm done ",Debug)<<"shmid:" <<shmid<<endl;
    

    CloseFifo(fd);
    
    
    return 0;
}   